package com.boarsoft.boar.deploy.mock;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.boarsoft.agent.AgentService;
import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.common.util.FileUtil;
import com.boarsoft.common.util.StreamUtil;
import com.boarsoft.flow.core.SimpleFlow;
import com.boarsoft.flow.core.SimpleFlowEngine;

@Component("fakeAgent")
public class FakeAgentServiceImpl implements AgentService {
	private static final Logger log = LoggerFactory.getLogger(FakeAgentServiceImpl.class);

	protected SimpleFlowEngine flowEngine;
	protected boolean windows;
	protected String SHELL_PATH = "/home/app/agent/shell";
	protected String FILE_PATH = "/home/app/agent/file";

	public FakeAgentServiceImpl() {
		String os = System.getProperty("os.name");
		windows = os.toLowerCase().startsWith("win");
	}

	@Override
	@Deprecated
	public ReplyInfo<Object> executeSql(String dbId, String path, String taskKey)
			throws UnsupportedEncodingException, IOException {
		return new ReplyInfo<Object>();
	}

	@Deprecated
	public ReplyInfo<Object> executeSql2(String dbId, String path) throws UnsupportedEncodingException, IOException {
		return new ReplyInfo<Object>();
	}

	@Override
	@Deprecated
	public ReplyInfo<Object> executeShell(String path, String[] args, String taskKey) {
		return new ReplyInfo<Object>();
	}

	@Override
	@Deprecated
	public ReplyInfo<Object> executeShell(String user, String addr, String parent, String path, String[] args, String taskKey) {
		log.info("Execute {} with {}", path, args);
		return new ReplyInfo<Object>();
	}

	@Override
	@Deprecated
	public ReplyInfo<Object> executeShell(String parent, String path, String[] args, String taskKey) {
		log.info("Execute {} with {}", path, args);
		StringBuilder sb = new StringBuilder();
		sb.append("sh ").append(parent).append("/").append(path);
		if (args != null) {
			for (String a : args) {
				sb.append(" ").append(a);
			}
		}
		String cmd = sb.toString();
		return this.executeShell(cmd);
	}

	@Override
	@Deprecated
	public ReplyInfo<Object> executeCmd(String code, String[] args, String taskKey) {
		log.info("Execute {} with {}", code, args);
		StringBuilder sb = new StringBuilder();
		sb.append("sh ").append(SHELL_PATH)//
				.append("/").append(code).append(".sh");
		if (args != null) {
			for (String a : args) {
				sb.append(" ").append(a);
			}
		}
		String cmd = sb.toString();
		return this.executeShell(cmd);
	}

	@Override
	public ReplyInfo<Object> executeShell2(String user, String addr, String cmd, String taskKey) {
		String to = new StringBuilder(user).append("@").append(addr).toString();
		log.debug("Remote execute shell: [ssh {} '{}']", to, cmd);
		return this.executeShell(new String[] { "ssh", to, cmd });
	}

	/**
	 * 指定给定的SHELL
	 *
	 * @param cmds
	 * @return
	 */
	@Override
	public ReplyInfo<Object> executeShell(String[] cmds) {
		// if (cmds == null || cmds.length < 1) {
		// throw new IllegalArgumentException("Command can not be empty");
		// }
		log.info("Execute commands:");
		for (int i = 0; i < cmds.length; i++) {
			log.info("{}={}", i, cmds[i]);
		}
		return new ReplyInfo<Object>();
	}

	@Override
	public ReplyInfo<Object> start(String flowId, Object data) throws Throwable {
		log.info("Start flow {}", flowId);
		SimpleFlow flow = flowEngine.start(flowId, data);
		log.info("Flow {} completed", flow);
		return new ReplyInfo<Object>();
	}

	// -------------------------

	@Override
	public ReplyInfo<Object> copy2(String from, String to, List<String> ipLt, int port) throws Throwable {
		for (String ip : ipLt) {
			this.copy2(from, to, ip, port);
		}
		return new ReplyInfo<Object>(true, "");
	}

	@Override
	public void write2(int index, String to, byte[] buf, int off, int len) throws Throwable {
		File f = new File(new StringBuilder().append(FILE_PATH)//
				.append("/").append(to).toString());
		if (index == 0) {
			log.info("Writing file {}", f.getAbsolutePath());
		}
		FileUtil.makePath(f.getParent()); // 创建目录
		BufferedOutputStream bos = null;
		try {
			bos = new BufferedOutputStream(new FileOutputStream(f, index > 0));
			bos.write(buf, off, len);
		} finally {
			StreamUtil.close(bos);
		}
	}

	@Override
	public boolean exists(String path) {
		log.info("Check if file {} exists", path);
		return new File(path).exists();
	}

	@Override
	public void copy2(String from, String to, String addr) throws Throwable {
		log.info("Copy file {} to {} {}", from, addr, to);
	}

	@Override
	public void copy2(String from, String to, String ip, int port) throws Throwable {
		String addr = new StringBuilder().append(ip).append(":").append(port).toString();
		this.copy2(from, to, addr);
	}

	@Override
	public ReplyInfo<Object> executeCmd(String path, String[] args) {
		return this.executeShell(SHELL_PATH, path, args);
	}

	@Override
	public ReplyInfo<Object> executeShell(String path, String[] args) {
		return this.executeShell(FILE_PATH, path, args);
	}

	@Override
	public ReplyInfo<Object> executeShell(String parent, String path, String[] args) {
		log.info("Execute shell {} with {}", path, args);
		StringBuilder sb = new StringBuilder();
		if (windows) {
			sb.append(parent).append("/").append(path);
			if (args != null) {
				for (String a : args) {
					sb.append(" ").append(a);
				}
			}
		} else {
			sb.append("sh ").append(parent).append("/").append(path);
			if (args != null) {
				for (String a : args) {
					sb.append(" ").append(a);
				}
			}
		}
		String cmd = sb.toString();
		return this.executeShell(cmd);
	}

	@Override
	public ReplyInfo<Object> executeShell(String cmd) {
		if (windows) {
			// log.debug("Execute shell: [start /c '{}']", cmd);
			return this.executeShell(new String[] { cmd });
		} else {
			log.debug("Execute shell: [sh -c '{}']", cmd);
			return this.executeShell(new String[] { "sh", "-c", cmd });
		}
	}

	@Override
	public ReplyInfo<Object> unzip(String sp, String tp) throws IOException {
		sp = new StringBuilder().append(FILE_PATH)//
				.append("/").append(sp).toString();
		log.info("Unzip {} to {}", sp, tp);
		return new ReplyInfo<Object>();
	}

	@Override
	public ReplyInfo<Object> delete(String path) {
		return new ReplyInfo<Object>();
	}

	@Override
	public ReplyInfo<Object> copy2(String from, String to) throws Throwable {
		return new ReplyInfo<Object>();
	}
}